﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.Statistics;
using MathNet.Symbolics;

namespace NumericalAnalysis.DataInterpolation
{
    internal class AitkenInterpolationEpsilon
    {

        Vector<double> theVec = Vector<double>.Build.Dense(2);
        List<Vector<double>> vectors = new List<Vector<double>>();
        List<int> recurrenceNums = new List<int>();

        int count = 0;

        public AitkenInterpolationEpsilon(IEnumerable<Vector<double>> _vectors)
        {
            count = _vectors.Count();
            vectors = _vectors.ToList();
        }

        public AitkenInterpolationEpsilon(IEnumerable<Tuple<double, double>> _tuples)
        {
            count = _tuples.Count();
            vectors = _tuples.Select(v =>
            {
                var vec = Vector<double>.Build.Dense(2);
                vec[0] = v.Item1;
                vec[1] = v.Item2;
                return vec;
            }).ToList();
        }



        public IList<double> FitInterpolationEpsilon(double epsilon = 1e-3)
        {

            List<double> xs = vectors.Select(v => v[0]).ToList();
            List<double> ys = vectors.Select(v => v[1]).ToList();

            for (int k = 0; k < count; k++)
            {
                var valNexts = vectors.Select(v => 0d).ToList();
                var valPervs = ys;
                double tol = 1;
                int ii = 0;
                for (int i = 0; i < count - 1; i++)
                {
                    ii = i;
                    for (int j = i + 1; j < count; j++)
                    {
                        var xk = xs[i];
                        var xn = xs[j];
                        var pk = valPervs[i];
                        var pn = valPervs[j];
                        valNexts[j] = (pk * (xn - xs[k]) - pn * (xk - xs[k])) / (xn - xk);
                        tol = Math.Abs(valPervs[i + 1] - valNexts[i + 1]);
                        if (tol < epsilon) break;
                    }
                }
                ys.Add(valNexts[ii + 1]);
                recurrenceNums.Append(ii + 1);
            }

            return ys;
        }


    }

    public class AitkenInterpolationEpsilonTest
    {
        /// <summary>
        /// sin函数
        /// </summary>
        /// <returns></returns>
        public static void ExampleSin()
        {
            List<Tuple<double, double>> extVecs = new List<Tuple<double, double>>();
            //构造sin函数插值点
            List<double> xs = NumericalService.LinSpace(0, Math.PI * 2, Math.PI * 2 * 0.1);
            extVecs = NumericalService.CalcByFunc((x) => { return Math.Sin(x); }, xs).ToList();
            //进行插值 
            var interp = new AitkenInterpolationEpsilon(extVecs);
            var ys = interp.FitInterpolationEpsilon(0.1).ToList();

            Console.WriteLine(ys[3]);
            Console.WriteLine(Math.Sin(xs[3]));

            //List<Tuple<double, double>> curvePnts = new List<Tuple<double, double>>();

            //List<double> array2 = NumericalService.LinSpace(0 + 0.5, 9 - 0.5, 0.01);
            //curvePnts = NumericalService.CalcByFunc(CalculateBy, array2).ToList();
            //return (ys, curvePnts);
        }





    }

}
